﻿using AutoMapper;
using HamcoWcs.DAL;
using HamcoWcs.Entitys.BaseConfigs;
using HamcoWcs.Models.Common;
using HamcoWcs.Models.DbInfos;
using HamcoWcs.Models.Devices;
using HamcoWcs.Models.Monitors;
using HamcoWcs.Models.NodeInfos;
using HamcoWcs.Models.PlcInfos;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;

namespace HamcoWcs.Service.Common
{
    public partial class AutomaticStorageInfo
    {
        public static void RefreshAlarms(List<AlarmExplanation> alarms)
        {
            Alarms.Clear();
            alarms.AddRange(alarms);
        }

        private void InitAlarms(WcsDbContext wcsDbContext)
        {
            Alarms = wcsDbContext.AlarmExplanations.ToList();
            MonitorConData.RefreshAlarms(Alarms.Where(x => x.Module == "pcon").ToList());
            MonitorSrmData.RefreshAlarms(Alarms.Where(x => x.Module == "srm").ToList());
        }

        private void InitSrm(WcsDbContext wcsDbContext)
        {
            var srmInfos = wcsDbContext.PlcInfos.Where(x => x.PlcType == "Srm").Include(x => x.DbInfos).AsNoTracking().ToList();
            if (srmInfos.Count <= 0) return;


            foreach (var srmInfo in srmInfos)
            {
                var plcInfo = _mapper.Map<PlcInfoDto>(srmInfo);
                var dbInfo = _mapper.Map<List<DbInfoDto>>(srmInfo.DbInfos);
                var srm = new SrmPlc(srmInfo.PlcName, plcInfo, dbInfo);

                var srmEntities = wcsDbContext.SrmInfos.Where(x => x.PlcName == srmInfo.PlcName).AsNoTracking().ToList();
                var srmDtos = _mapper.Map<List<SrmDto>>(srmEntities);


                foreach (var srmDto in srmDtos)
                {
                    if (srmDto.MachineName == "CJSTW100" && srmDto.PortName == "C1")
                        srmDto.BlockedBays.AddRange(new int[] { 1, 2, 3, 4 });
                    if (srmDto.MachineName == "CJSTW100" && srmDto.PortName == "C2")
                        srmDto.BlockedBays.AddRange(new int[] { 39, 40, 41, 42 });
                    if (srmDto.MachineName == "CJSTW200" && srmDto.PortName == "C1")
                        srmDto.BlockedBays.AddRange(new int[] { 1, 2, 3, 4 });
                    if (srmDto.MachineName == "CJSTW200" && srmDto.PortName == "C2")
                        srmDto.BlockedBays.AddRange(new int[] { 56, 57, 58, 59 });

                    srm.Srms.TryAdd(srmDto.SrmName, srmDto);

                    var node = this.Nodes.FirstOrDefault(x => x.NodeName == srmDto.MachineName);

                    try
                    {
                        srmDto.Aisle = node;
                        node.SrmPlc = srm;
                    }
                    catch (Exception ex)
                    {
                        Debug.Assert(false);
                    }
                }
                SrmDic.TryAdd(srmInfo.PlcName, srm);
            }

            foreach (var srmPlc in SrmDic.Values)
            {

                foreach (var srm in srmPlc.Srms.Values)
                {
                    var machineName = srm.MachineName;
                    var portName = srm.PortName;
                    var anotherPortName = portName == "C1" ? "C2" : "C1";
                    srm.AnotherSrm = srmPlc.Srms.Values.FirstOrDefault(x => x.MachineName == machineName && x.PortName == anotherPortName);
                }
            }
        }

        private void InitPcon(WcsDbContext wcsDbContext)
        {
            var conveyorInfos = wcsDbContext.PlcInfos.Where(x => x.PlcType == GlobalValue.PALLET_PLC_TYPE).Include(x => x.DbInfos).AsNoTracking().ToList();


            if (conveyorInfos.Count <= 0) return;

            foreach (var conveyorInfo in conveyorInfos)
            {
                var plcInfo = _mapper.Map<PlcInfoDto>(conveyorInfo);
                var dbInfo = _mapper.Map<List<DbInfoDto>>(conveyorInfo.DbInfos);
                var plc = new PconPlc(conveyorInfo.PlcName, plcInfo, dbInfo);

                //conveyor.PconPlcInfo = _mapper.Map<PlcInfoDto>(conveyorInfo);
                //conveyor.DbInfo = _mapper.Map<IEnumerable<DbInfoDto>>(conveyorInfo.DbInfos).ToList();
                var conveyorAddInfoEntitys = wcsDbContext.PconInfos.Where(x => x.PlcName == conveyorInfo.PlcName).AsNoTracking().ToList();
                var conDtos = _mapper.Map<List<PconDto>>(conveyorAddInfoEntitys);
                foreach (var conDto in conDtos)
                {
                    plc.Pcons.TryAdd(conDto.PconName, conDto);

                    var node = this.Nodes.FirstOrDefault(x => x.NodeName == conDto.MachineName);
                    try
                    {
                        if (node == null) continue;
                        node.Pcons.Add(conDto);
                        conDto.Machine = node;
                    }
                    catch (Exception ex)
                    {
                        throw;
                    }
                }

                plc.Rasters = _mapper.Map<List<RasterDto>>(wcsDbContext.Rasters.ToList());
                foreach (var rasterDto in plc.Rasters)
                {
                    rasterDto.CalcOffset();
                }

                ConveyorDic.TryAdd(plc.PlcName, plc);
            }
        }


        public string GetExcuteSrm(string wcsZone, string aisle)
        {
            throw new NotImplementedException();
            //if (!string.IsNullOrEmpty(wcsZone)) { }
        }


        public string GetPortAisle(string machineName)
        {
            throw new NotImplementedException();
        }


        public AutomaticStorageInfo(IServiceScopeFactory scopeFactory, IMapper mapper)
        {
            _scopeFactory = scopeFactory;
            _mapper = mapper;

            using (var scope = _scopeFactory.CreateScope())
            {
                var wcsDbContext = scope.ServiceProvider.GetRequiredService<WcsDbContext>();
                Nodes = _mapper.Map<List<NodeInfoDto>>(wcsDbContext.NodeInfos.ToList());
                try
                {
                    InitPcon(wcsDbContext);
                    InitSrm(wcsDbContext);
                    InitAlarms(wcsDbContext);
                }
                catch (Exception ex)
                {
                    throw;
                }
            }
        }
    }



}
